package com.chenliang.swagger.service.impl;


import com.chenliang.swagger.model.ModelAttr;
import com.chenliang.swagger.model.Request;
import com.chenliang.swagger.model.Response;
import com.chenliang.swagger.model.Table;
import com.chenliang.swagger.service.WordService;
import com.chenliang.swagger.utils.JsonUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @program: myes
 * @description:
 * @author: 陈英俊
 * @create: 2021-09-09 10:50
 */
@Service
public class WordServiceImpl  implements WordService {

    Logger log = LoggerFactory.getLogger(WordServiceImpl.class);
    @Autowired
    private RestTemplate restTemplate;

    public WordServiceImpl() {
    }

    public Map<String, Object> tableList(String swaggerUrl) {
        Map<String, Object> resultMap = new HashMap();
        ArrayList result = new ArrayList();

        try {
            String jsonStr = this.restTemplate.getForObject(swaggerUrl, String.class);
            Map<String, Object> map = (Map) JsonUtils.decode(jsonStr, HashMap.class);
            Map<String, ModelAttr> definitinMap = this.parseDefinitions(map);
            Map<String, Map<String, Object>> paths = (Map)map.get("paths");
            if (paths != null) {
                Iterator it = paths.entrySet().iterator();

                while(it.hasNext()) {
                    Map.Entry<String, Map<String, Object>> path = (Map.Entry)it.next();
                    Iterator<Map.Entry<String, Object>> it2 = ((Map)path.getValue()).entrySet().iterator();
                    String url = path.getKey();
                    String requestType = StringUtils.join(((Map)path.getValue()).keySet(), ",");
                    Map.Entry<String, Object> firstRequest = it2.next();
                    Map<String, Object> content = (Map)firstRequest.getValue();
                    String title = String.valueOf(((List)content.get("tags")).get(0));
                    String tag = String.valueOf(content.get("summary"));
                    String description = String.valueOf(content.get("summary"));
                    String requestForm = "";
                    List<String> consumes = (List)content.get("consumes");
                    if (consumes != null && consumes.size() > 0) {
                        requestForm = StringUtils.join(consumes, ",");
                    }

                    String responseForm = "";
                    List<String> produces = (List)content.get("produces");
                    if (produces != null && produces.size() > 0) {
                        responseForm = StringUtils.join(produces, ",");
                    }

                    List<LinkedHashMap> parameters = (ArrayList)content.get("parameters");
                    Map<String, Object> responses = (LinkedHashMap)content.get("responses");
                    Table table = new Table();
                    table.setTitle(title);
                    table.setUrl(url);
                    table.setTag(tag);
                    table.setDescription(description);
                    table.setRequestForm(requestForm);
                    table.setResponseForm(responseForm);
                    table.setRequestType(requestType);
                    table.setRequestList(this.processRequestList(parameters));
                    table.setResponseList(this.processResponseCodeList(responses));
                    Map<String, Object> obj = (Map)responses.get("200");
                    if (obj != null && obj.get("schema") != null) {
                        table.setModelAttr(this.processResponseModelAttrs(obj, definitinMap));
                    }

                    table.setRequestParam(this.processRequestParam(table.getRequestList(), definitinMap));
                    table.setResponseParam(this.processResponseParam(obj, definitinMap));
                    result.add(table);
                }
            }

            Map<String, List<Table>> tableMap = (Map)((Stream)result.stream().parallel()).collect(Collectors.groupingBy(Table::getTitle));
            resultMap.put("tableMap", new TreeMap(tableMap));
            resultMap.put("info", map.get("info"));
            this.log.debug(JsonUtils.encode(resultMap));
        } catch (Exception var26) {
            this.log.error("parse error", var26);
        }

        return resultMap;
    }

    private List<Request> processRequestList(List<LinkedHashMap> parameters) {
        List<Request> requestList = new ArrayList();
        if (!CollectionUtils.isEmpty(parameters)) {
            Iterator var3 = parameters.iterator();

            while(var3.hasNext()) {
                Map<String, Object> param = (Map)var3.next();
                Object in = param.get("in");
                Request request = new Request();
                request.setName(String.valueOf(param.get("name")));
                request.setType(param.get("type") == null ? "object" : param.get("type").toString());
                request.setParamType(String.valueOf(in));
                if (in != null && "body".equals(in)) {
                    Map<String, Object> schema = (Map)param.get("schema");
                    Object ref = schema.get("$ref");
                    if (schema.get("type") != null && "array".equals(schema.get("type"))) {
                        ref = ((Map)schema.get("items")).get("$ref");
                    }

                    request.setParamType(ref == null ? "{}" : ref.toString());
                }

                request.setRequire(false);
                if (param.get("required") != null) {
                    request.setRequire((Boolean)param.get("required"));
                }

                request.setRemark(String.valueOf(param.get("description")));
                request.setParamType(request.getParamType().replaceAll("#/definitions/", ""));
                requestList.add(request);
            }
        }

        return requestList;
    }

    private List<Response> processResponseCodeList(Map<String, Object> responses) {
        List<Response> responseList = new ArrayList();

        Response response;
        for(Iterator resIt = responses.entrySet().iterator(); resIt.hasNext(); responseList.add(response)) {
            Map.Entry<String, Object> entry = (Map.Entry)resIt.next();
            response = new Response();
            response.setName(entry.getKey());
            LinkedHashMap<String, Object> statusCodeInfo = (LinkedHashMap)entry.getValue();
            response.setDescription(String.valueOf(statusCodeInfo.get("description")));
            Object schema = statusCodeInfo.get("schema");
            if (schema != null) {
                Object originalRef = ((LinkedHashMap)schema).get("originalRef");
                response.setRemark(originalRef == null ? "" : originalRef.toString());
            }
        }

        return responseList;
    }

    private ModelAttr processResponseModelAttrs(Map<String, Object> responseObj, Map<String, ModelAttr> definitinMap) {
        Map<String, Object> schema = (Map)responseObj.get("schema");
        String type = (String)schema.get("type");
        String ref = null;
        if ("array".equals(type)) {
            Map<String, Object> items = (Map)schema.get("items");
            if (items != null && items.get("$ref") != null) {
                ref = (String)items.get("$ref");
            }
        }

        if (schema.get("$ref") != null) {
            ref = (String)schema.get("$ref");
        }

        ModelAttr modelAttr = new ModelAttr();
        modelAttr.setType(StringUtils.defaultIfBlank(type, ""));
        if (StringUtils.isNotBlank(ref) && definitinMap.get(ref) != null) {
            modelAttr = definitinMap.get(ref);
        }

        return modelAttr;
    }

    private Map<String, ModelAttr> parseDefinitions(Map<String, Object> map) {
        Map<String, Map<String, Object>> definitions = (Map)map.get("definitions");
        Map<String, ModelAttr> definitinMap = new HashMap(256);
        ArrayList attrList;
        ModelAttr modeAttr;
        if (definitions != null) {
            Iterator modelNameIt = definitions.keySet().iterator();

            label73:
            while(true) {
                String modeName;
                Map modeProperties;
                do {
                    if (!modelNameIt.hasNext()) {
                        break label73;
                    }

                    modeName = (String)modelNameIt.next();
                    modeProperties = (Map) definitions.get(modeName).get("properties");
                } while(modeProperties == null);

                Iterator<Map.Entry<String, Object>> mIt = modeProperties.entrySet().iterator();

                for(attrList = new ArrayList(); mIt.hasNext(); attrList.add(modeAttr)) {
                    Map.Entry<String, Object> mEntry = mIt.next();
                    Map<String, Object> attrInfoMap = (Map)mEntry.getValue();
                    modeAttr = new ModelAttr();
                    modeAttr.setName(mEntry.getKey());
                    modeAttr.setType((String)attrInfoMap.get("type"));
                    if (attrInfoMap.get("format") != null) {
                        modeAttr.setType(modeAttr.getType() + "(" + attrInfoMap.get("format") + ")");
                    }

                    modeAttr.setType(StringUtils.defaultIfBlank(modeAttr.getType(), "object"));
                    modeAttr.setDescription((String)attrInfoMap.get("description"));
                    if ("array".equals(modeAttr.getType())) {
                        modeAttr.setIsHaveChildPro("true");
                        Map i = (Map)attrInfoMap.get("items");
                        modeAttr.setType((String)i.get("$ref"));
                    }
                }

                 modeAttr = new ModelAttr();
                Object title = definitions.get(modeName).get("title");
                Object description = definitions.get(modeName).get("description");
                modeAttr.setClassName(title == null ? "" : title.toString());
                modeAttr.setDescription(description == null ? "" : description.toString());
                modeAttr.setProperties(attrList);
                definitinMap.put("#/definitions/" + modeName, modeAttr);
            }
        }

        Map<String, ModelAttr> resultMap = new HashMap(256);
        resultMap.putAll(definitinMap);
        Iterator var15 = definitinMap.entrySet().iterator();

        while(var15.hasNext()) {
            Map.Entry<String, ModelAttr> entry = (Map.Entry)var15.next();
            new ModelAttr();
            attrList = new ArrayList();
            List<ModelAttr> maPro = entry.getValue().getProperties();
            Iterator var20 = maPro.iterator();

            while(var20.hasNext()) {
                modeAttr = (ModelAttr)var20.next();
                if ("true".equals(modeAttr.getIsHaveChildPro())) {
                    ModelAttr moa = new ModelAttr();
                    ModelAttr m = definitinMap.get(modeAttr.getType());
                    moa.setName(modeAttr.getName());
                    moa.setDescription(modeAttr.getDescription());
                    if (StringUtils.isNotEmpty(modeAttr.getType())) {
                        moa.setType(modeAttr.getType().replaceAll("#/definitions/", ""));
                    }

                    if (m != null) {
                        moa.setProperties(m.getProperties());
                    }

                    attrList.add(moa);
                } else {
                    attrList.add(modeAttr);
                }
            }

            entry.getValue().setProperties(attrList);
        }

        return definitinMap;
    }

    private String processResponseParam(Map<String, Object> responseObj, Map<String, ModelAttr> definitinMap) throws JsonProcessingException {
        if (responseObj != null && responseObj.get("schema") != null) {
            Map<String, Object> schema = (Map)responseObj.get("schema");
            String type = (String)schema.get("type");
            String ref = null;
            if ("array".equals(type)) {
                Map<String, Object> items = (Map)schema.get("items");
                if (items != null && items.get("$ref") != null) {
                    ref = (String)items.get("$ref");
                }
            }

            if (schema.get("$ref") != null) {
                ref = (String)schema.get("$ref");
            }

            if (StringUtils.isNotEmpty(ref)) {
                ModelAttr modelAttr = definitinMap.get(ref);
                if (modelAttr != null && !CollectionUtils.isEmpty(modelAttr.getProperties())) {
                    Map<String, Object> responseMap = new HashMap(8);
                    Iterator var8 = modelAttr.getProperties().iterator();

                    while(true) {
                        while(var8.hasNext()) {
                            ModelAttr subModelAttr = (ModelAttr)var8.next();
                            if (subModelAttr.getProperties().size() > 0) {
                                Map<String, Object> subResponseMap = new HashMap();
                                Iterator var11 = subModelAttr.getProperties().iterator();

                                while(var11.hasNext()) {
                                    ModelAttr sub2ModelAttr = (ModelAttr)var11.next();
                                    subResponseMap.put(sub2ModelAttr.getName(), sub2ModelAttr.getType());
                                }

                                List<Map> mapList = new ArrayList();
                                mapList.add(subResponseMap);
                                responseMap.put(subModelAttr.getName(), mapList);
                            } else {
                                responseMap.put(subModelAttr.getName(), subModelAttr.getType());
                            }
                        }

                        return JsonUtils.encode(responseMap);
                    }
                }
            }
        }

        return "";
    }

    private String processRequestParam(List<Request> list, Map<String, ModelAttr> definitinMap) throws IOException {
        Map<String, Object> paramMap = new HashMap(8);
        if (list != null && list.size() > 0) {
            Iterator var4 = list.iterator();

            while(true) {
                while(var4.hasNext()) {
                    Request request = (Request)var4.next();
                    String name = request.getName();
                    String type = request.getType();
                    byte var9 = -1;
                    switch(type.hashCode()) {
                        case -1034364087:
                            if (type.equals("number")) {
                                var9 = 2;
                            }
                            break;
                        case -1023368385:
                            if (type.equals("object")) {
                                var9 = 5;
                            }
                            break;
                        case -891985903:
                            if (type.equals("string")) {
                                var9 = 0;
                            }
                            break;
                        case 3029410:
                            if (type.equals("body")) {
                                var9 = 4;
                            }
                            break;
                        case 64711720:
                            if (type.equals("boolean")) {
                                var9 = 3;
                            }
                            break;
                        case 1958052158:
                            if (type.equals("integer")) {
                                var9 = 1;
                            }
                    }

                    switch(var9) {
                        case 0:
                            paramMap.put(name, "string");
                            break;
                        case 1:
                            paramMap.put(name, 0);
                            break;
                        case 2:
                            paramMap.put(name, 0.0D);
                            break;
                        case 3:
                            paramMap.put(name, true);
                            break;
                        case 4:
                        case 5:
                            ModelAttr modelAttr = definitinMap.get("#/definitions/" + request.getParamType());
                            if (modelAttr != null && !CollectionUtils.isEmpty(modelAttr.getProperties())) {
                                Iterator var11 = modelAttr.getProperties().iterator();

                                while(var11.hasNext()) {
                                    ModelAttr subModelAttr = (ModelAttr)var11.next();
                                    paramMap.put(subModelAttr.getName(), subModelAttr.getType());
                                }
                                break;
                            }
                        default:
                            paramMap.put(name, null);
                    }
                }

                return JsonUtils.encode(paramMap);
            }
        } else {
            return JsonUtils.encode(paramMap);
        }
    }
}
